package view;

import client.Client;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

/**
 *
 * MainWindow: The view where the client interact with the client class. Then
 * the client class communicates with the server.
 */
public class MainWindow extends javax.swing.JFrame implements MainWindowInterface {

    private MainWindow mainWindow;
    private List<JPanel> barPanelList;
    private int currentBar;

    /**
     * Creates new form MainWindow
     */
    public MainWindow() {

        this.mainWindow = this;
        this.currentBar = 0;
        this.barPanelList = new ArrayList<>(); //Array of the transfer bars.

        initComponents();

        this.jTree1.setModel(null); //Empty the default tree.
        setExtendedState(MAXIMIZED_BOTH); //Maximized window.
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
        top = new javax.swing.JPanel();
        filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        jLabel1 = new javax.swing.JLabel();
        filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        filler12 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
        mid = new javax.swing.JPanel();
        folderTitles = new javax.swing.JPanel();
        filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        jLabel2 = new javax.swing.JLabel();
        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        folders = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        foldersButtons = new javax.swing.JPanel();
        filler7 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        jButton1 = new javax.swing.JButton();
        filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        refresh = new javax.swing.JButton();
        filler14 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        jButton2 = new javax.swing.JButton();
        filler8 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        transfers = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        barPanel = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("SimpleFTP");
        setMinimumSize(new java.awt.Dimension(800, 400));
        setPreferredSize(new java.awt.Dimension(800, 600));
        getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.Y_AXIS));
        getContentPane().add(filler1);

        top.setLayout(new javax.swing.BoxLayout(top, javax.swing.BoxLayout.X_AXIS));
        top.add(filler5);

        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/view/resources/title.png"))); // NOI18N
        top.add(jLabel1);
        top.add(filler4);

        getContentPane().add(top);
        getContentPane().add(filler12);

        mid.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        mid.setLayout(new javax.swing.BoxLayout(mid, javax.swing.BoxLayout.Y_AXIS));

        folderTitles.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
        folderTitles.setLayout(new javax.swing.BoxLayout(folderTitles, javax.swing.BoxLayout.X_AXIS));
        folderTitles.add(filler3);

        jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/view/resources/server.png"))); // NOI18N
        jLabel2.setText("Server");
        jLabel2.setInheritsPopupMenu(false);
        folderTitles.add(jLabel2);
        folderTitles.add(filler2);

        mid.add(folderTitles);

        folders.setLayout(new javax.swing.BoxLayout(folders, javax.swing.BoxLayout.X_AXIS));

        jTree1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
        jScrollPane1.setViewportView(jTree1);

        folders.add(jScrollPane1);

        mid.add(folders);

        foldersButtons.setLayout(new javax.swing.BoxLayout(foldersButtons, javax.swing.BoxLayout.X_AXIS));
        foldersButtons.add(filler7);

        jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/view/resources/down.png"))); // NOI18N
        jButton1.setText("Dowload");
        jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        foldersButtons.add(jButton1);
        foldersButtons.add(filler6);

        refresh.setIcon(new javax.swing.ImageIcon(getClass().getResource("/view/resources/refresh.png"))); // NOI18N
        refresh.setText("Refresh");
        refresh.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshActionPerformed(evt);
            }
        });
        foldersButtons.add(refresh);
        foldersButtons.add(filler14);

        jButton2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/view/resources/up.png"))); // NOI18N
        jButton2.setText("Upload");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });
        foldersButtons.add(jButton2);
        foldersButtons.add(filler8);

        mid.add(foldersButtons);

        getContentPane().add(mid);

        transfers.setPreferredSize(new java.awt.Dimension(186, 250));
        transfers.setLayout(new javax.swing.BoxLayout(transfers, javax.swing.BoxLayout.Y_AXIS));

        barPanel.setBackground(new java.awt.Color(255, 255, 255));
        barPanel.setLayout(new javax.swing.BoxLayout(barPanel, javax.swing.BoxLayout.Y_AXIS));
        jScrollPane3.setViewportView(barPanel);

        transfers.add(jScrollPane3);

        getContentPane().add(transfers);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        JFileChooser fc = new JFileChooser(); //Download button Action.
        try {
            fc.setSelectedFile(new File(jTree1.getLastSelectedPathComponent().toString()));
            int returnVal = fc.showSaveDialog(mainWindow); //Display the save window.
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File fileLocal = fc.getSelectedFile();
                Object[] downloadTreePathRemote = jTree1.getSelectionPath().getPath();
                StringBuilder sb = new StringBuilder();
                for (Object object : downloadTreePathRemote) { //Generate the path from the tree.
                    sb.append(object);
                    sb.append("/");
                }
                sb.replace(0, 1, "");
                sb.replace(sb.length() - 1, sb.length(), "");
                this.client.downloadFile(mainWindow, sb.toString(), fileLocal, currentBar);
            }
        } catch (NullPointerException e) {
            System.err.println("Error file not selected.");;
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        JFileChooser fc = new JFileChooser(); //Upload button Action.
        try {

            int returnVal = fc.showOpenDialog(mainWindow); //Display the upload window.
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File fileLocal = fc.getSelectedFile();
                Object[] downloadTreePathRemote = jTree1.getSelectionPath().getPath();
                StringBuilder sb = new StringBuilder();
                for (Object object : downloadTreePathRemote) { //Generate the path from the tree.
                    sb.append(object);
                    sb.append("/");
                }
                sb.replace(0, 1, "");
                sb.replace(sb.length() - 1, sb.length(), "");

                this.client.uploadFile(mainWindow, sb.toString(), fileLocal, currentBar);
            }
        } catch (NullPointerException e) {
            System.err.println("Error file not selected.");;
        }
    }//GEN-LAST:event_jButton2ActionPerformed

    private void refreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshActionPerformed

        client.listRemoteFiles(); //Refresh button Action.

    }//GEN-LAST:event_refreshActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel barPanel;
    private javax.swing.Box.Filler filler1;
    private javax.swing.Box.Filler filler12;
    private javax.swing.Box.Filler filler14;
    private javax.swing.Box.Filler filler2;
    private javax.swing.Box.Filler filler3;
    private javax.swing.Box.Filler filler4;
    private javax.swing.Box.Filler filler5;
    private javax.swing.Box.Filler filler6;
    private javax.swing.Box.Filler filler7;
    private javax.swing.Box.Filler filler8;
    private javax.swing.JPanel folderTitles;
    private javax.swing.JPanel folders;
    private javax.swing.JPanel foldersButtons;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTree jTree1;
    private javax.swing.JPanel mid;
    private javax.swing.JButton refresh;
    private javax.swing.JPanel top;
    private javax.swing.JPanel transfers;
    // End of variables declaration//GEN-END:variables

    private Client client; //Client class to interactions

    @Override
    public void setClient(Client client) {
        this.client = client;
        try {
            this.client.connect();
            this.client.listRemoteFiles();
        } catch (IOException ex) {
            System.err.println("Error on connect." + ex.getMessage());
        }
    }

    @Override
    public void setTree(Map<File, Map> mapFiles) {
        DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode("/"));
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
        root = mapFilesToTree(mapFiles, root);

        this.jTree1.setModel(model);

    }

    /**
     * Recursive function to conver a map to a Tree
     *
     * @param mapFiles Map<File, Map>
     * @param root root node.
     * @return DefaultMutableTreeNode root with all the childrens.
     */
    private DefaultMutableTreeNode mapFilesToTree(Map<File, Map> mapFiles, DefaultMutableTreeNode root) {

        DefaultMutableTreeNode node;

        for (File file : mapFiles.keySet()) {
            node = new DefaultMutableTreeNode(file.getName());
            if (mapFiles.get(file) != null) {
                mapFilesToTree(mapFiles.get(file), node);
            }
            root.add(node);
        }
        return root;
    }

    @Override
    public void addTransferBar() {
        JPanel bar = new javax.swing.JPanel();
        javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        javax.swing.JLabel jLabel = new javax.swing.JLabel();
        javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        javax.swing.JProgressBar jProgressBar1 = new javax.swing.JProgressBar();
        jProgressBar1.setStringPainted(true);
        javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        bar.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
        bar.setLayout(new javax.swing.BoxLayout(bar, javax.swing.BoxLayout.X_AXIS));
        bar.add(filler1);
        jLabel.setText("INFO");
        jLabel.setMinimumSize(new java.awt.Dimension(400, 24));
        jLabel.setPreferredSize(new java.awt.Dimension(400, 24));
        bar.add(jLabel);
        bar.add(filler2);
        bar.add(jProgressBar1);
        bar.add(filler3);
        this.barPanelList.add(bar);
        this.barPanel.add(this.barPanelList.get(this.currentBar));
        this.barPanel.revalidate();
        this.barPanel.repaint();
        this.currentBar++;
    }

    @Override
    public void setTransferBarInfo(int barNumber, String label, int pBValue, int finished) {
        JPanel bar = barPanelList.get(barNumber);
        JLabel jlabel = (JLabel) bar.getComponent(1);
        JProgressBar jProgressBar = (JProgressBar) bar.getComponent(3);
        jlabel.setText(label);
        jProgressBar.setValue(pBValue);
        jProgressBar.setString(Integer.toString(pBValue) + " %");
        if (finished == 1) {
            jProgressBar.setForeground(Color.decode("0x336633"));
        }
        bar.revalidate();
        bar.repaint();

    }

}
